home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
3_0
/
RAMSTART
/
RS(DLOG).C
< prev
next >
Wrap
Text File
|
1987-03-28
|
20KB
|
794 lines
/*
RS(Dlog).c
P/O RamStart.c
*/
#include <MacTypes.h>
#include <DialogMgr.h>
#include <ControlMgr.h>
#include <MemoryMgr.h>
#include <ResourceMgr.h>
#include <FileMgr.h>
#include <ToolboxUtil.h>
#include <EventMgr.h>
#include <SegmentLdr.h>
#include <SetJmp.h>
#include "RS.h"
extern jmp_buf env;
/* // */
/* Defined here */
static DialogPtr ctlW; /* Used by MakeCtlW(), ShowFileName(), */
/* TestDLOG(), and GetNewSize(). */
static long maxDisk; /* Set by MakeCtlW(); used also in GetNewSize(). */
pascal void Outline();
pascal Boolean DialogFilter();
NoRamDisk();
RestartUs();
/* // */
/* Display the control panel. Much must be done to set it up. The
controls must be set and the window displayed; the Update mechanism is
used to avoid redundant drawing. Then the "copying" message is moved to
a visible location. */
MakeCtlW( size )
long size; /* --> */
{
short type;
Handle item;
Rect box;
char sizePstr[32];
extern RamInfo ramInfo;
short dirSize;
Handle ramDirSize;
if( ctlW ) /* In case Main calls us twice. */
return;
ctlW = GetNewDialog( dlogCtl, NULL, -1 );
GetDItem( ctlW, ctlISet, &type, &item, &box ); /* disable the Set button but leave it reporting hits */
HiliteControl( item, 255 );
GetDItem( ctlW, dlogIScroll, &type, &item, &box ); /* Set up the control. */
SetCtlMin( item, MinDisk/1024 );
maxDisk = (ramInfo.oldBufPtr - (Ptr)GetZone() - MinHeap) / 1024; /* Leaves room for application. */
SetCtlMax( item, maxDisk );
SetCtlValue( item, size /= 1024 );
GetDItem( ctlW, ctlIEdit, &type, &item, &box ); /* Set the editText field. */
NumToString( size, sizePstr );
SetIText( item, sizePstr );
GetDItem( ctlW, ctlIOutline, &type, &item, &box ); /* set the Outline user item code */
SetDItem( ctlW, ctlIOutline, type, Outline, &box );
GetDItem( ctlW, ctlIBigDir, &type, &item, &box );
dirSize = 0;
ramDirSize = GetResource( 'RAMD', 257 );
if( ramDirSize )
dirSize = *(long *)*ramDirSize > 1;
SetCtlValue( item, dirSize );
myHideDItem( ctlW, ctlIFile );
myHideDItem( ctlW, ctlIOpenMsg );
myHideDItem( ctlW, ctlICopyMsg );
ShowWindow( ctlW );
BeginUpdate( ctlW ); /* Normally done via Update event. */
DrawDialog( ctlW );
EndUpdate( ctlW );
myShowDItem( ctlW, ctlIFile ); /* show "Copying" message */
InitCursor();
}
/* // */
/* If a RAM disk is already installed, ask the user what to do about it.
In the event that the current System file is on the RAM disk, don't let
the user remove the RAM disk.
This would be just an alert if we didn't have to gray the buttons. */
short DoAlready( dqp )
DrvQElPtr dqp;
{
DialogPtr already;
short sysDrvNum;
Handle dh;
short id;
long rType;
Str255 rName;
short type;
Handle item;
Rect box;
short itemHit;
already = GetNewDialog( dlogAlready, NULL, -1 );
GetDItem( already, alreadyIOutline, &type, &item, &box );
SetDItem( already, alreadyIOutline, type, Outline, &box );
/* Is the System file on the RAM disk? From the FCB for the System file,
go to the VCB and get the vcbDrvNum. */
sysDrvNum = *(short *)&( *(char **)&(FCBSPtr)[SysMap+20] )[72];
if( sysDrvNum == dqp->dQDrive ) { /* Don't let them remove the RAM disk if it has... */
GrayBtn( already, alreadyIRemove ); /* ...the active System file */
GrayBtn( already, alreadyINew );
}
else { /* slide "boot disk" message off the window */
GetDItem( already, alreadyIBoot, &type, &item, &box );
OffsetRect( &box, 1000, 0 );
SetDItem( already, alreadyIBoot, type, item, &box );
}
SysBeep( 6 );
ShowWindow( already );
InitCursor();
ModalDialog( NULL, &itemHit );
DisposeWindow( already );
return( itemHit );
}
/* // */
/* Show in the ctlW which file we're opening or copying. */
ShowFileName( name, dItem )
Ptr name; /* --> */
short dItem; /* --> */
{
short type;
Handle item;
Rect box;
char text[MAXLINE];
ParamText( name, NULL, NULL, NULL ); /* Also used by CopyFolder(). */
GetDItem( ctlW, dItem, &type, &item, &box ); /* get the message */
GetIText( item, text );
GetDItem( ctlW, ctlIFile, &type, &item, &box ); /* draw the message */
SetIText( item, text );
#if 0
SetPort( ctlW );
BeginUpdate( ctlW ); /* Normally done via Update event. */
DrawDialog( ctlW );
EndUpdate( ctlW );
#endif
}
/* // */
/* Check if the user clicked in the controls box. This normally would be
handled in a main event loop, but this program doesn't have one. The
program is more like a single command that would have highlited the menu
bar.
We respond as if in a modal dialog. In fact, ModalDialog will eventually
be called if any control was pressed, with the event that caused its
activation; thus, pressing in a button will hilite it, instead of having to
press twice. The only difficulty is in getting rid of the other events
that don't cause us to call ModalDialog.
Initially, the default button is Help, but once the user starts to change
the size of the disk, the Set button is the default. Thus, the user can
type a new size and then press Return. The Set button is item 1, but is
initially inactive. The Help button is outlined, so we respond to Return
or Enter as if the Help button had been pressed.
This is called from inside the file copying routines, which open lots of
files and create a couple of large heap structures. Rather than call
GetNewSize() directly, we give other routines a chance to clean up (and get
off the stack) by signalling the need to get the size.
*/
TestDLOG()
{
EventRecord theEvent;
GrafPtr oldPort;
Point thePoint;
long i;
short type;
Handle item;
Rect box;
/* // */
while( EventAvail( everyEvent, &theEvent ) ) {
if( theEvent.what == updateEvt ) { /* Usually caused by Help window disappearing. */
BeginUpdate( theEvent.message ); /* Note that the update event goes away now, */
DrawDialog( theEvent.message ); /* so don't call GetNextEvent on this one. */
EndUpdate( theEvent.message );
continue; /* the update event is cleared so don't get it below */
}
else if( IsDialogEvent(&theEvent) ) {
if( theEvent.what == keyDown ) {
if( (theEvent.message & charCodeMask) == '\r'/* Return == Help button. */
|| (theEvent.message & charCodeMask) == '\3' )
{
GetNextEvent( keyDownMask, &theEvent ); /* Used this event. */
DoHelp();
continue;
}
else longjmp( env, 'SZ' ); /* Never returns. GetNewSize() gets current event. */
}
else if( theEvent.what == mouseDown ) {
GetPort( &oldPort );
SetPort( ctlW ); /* Safe 'cause its our only dialog. */
thePoint = theEvent.where;
GlobalToLocal( &thePoint );
/* If the mouse was pressed in one of our controlling objects, do it.
The Help button doesn't cause the program to restart. */
for( i = ctlISet; i <= ctlIBigDir; ++i ) {
GetDItem( ctlW, i, &type, &item, &box );
if( PtInRect(thePoint, &box) ) {
if( i == ctlIHelp )
break;
if( i == ctlISet ) /* If Set button, drop this click so the user can... */
GetNextEvent( mDownMask, &theEvent ); /* ...still set the size. */
longjmp( env, 'SZ' ); /* Never returns. GetNewSize() gets current event. */
}
}
GetNextEvent( mDownMask, &theEvent ); /* Used this event. Get it now so TrackControl() */
/* isn't confused. */
if( i == ctlIHelp && TrackControl(item, thePoint, NULL) )
DoHelp();
SetPort( oldPort );
continue;
}
}
/* We don't want this one. Drop _this_ event, by its type. */
GetNextEvent( 1 << theEvent.what, &theEvent );
}
}
/* // */
/* They're trying to change the size of the RAM disk. Handle the dialog box
as a real dialog now. The EditText field may be used to directly set the size,
or the size may be dialed in with a scroll bar. The scroll bar's ActionProc
updates the EditText field.
The "Set" button becomes active when the user tries to set the size, i.e., upon
entry to this routine. It becomes the default button.
*/
GetNewSize()
/* the current event */
{
short type;
Handle item;
Rect box, setBox;
PenState penState;
GrafPtr oldPort;
long size;
char sizePstr[MAXLINE];
short itemHit;
void ShowNewSize();
Handle ramDesc, ramDirSize;
extern RamInfo ramInfo;
long heapSize, dirSize;
Ptr ramStart;
/* // */
/* Change the appearance of the dialog for setting the size. */
GetPort( &oldPort );
SetPort( ctlW );
myHideDItem( ctlW, ctlIFile ); /* Remove "Copying". */
GetDItem( ctlW, ctlISet, &type, &item, &setBox ); /* activate "Set" button and... */
HiliteControl( item, 0 );
PenMode( notPatCopy ); /* ...deoutline "Help" button. */
Outline( ctlW, (short)ctlIOutline );
GetDItem( ctlW, ctlIOutline, &type, &item, &box );
SetDItem( ctlW, ctlIOutline, type, item, &setBox );
PenNormal();
Outline( ctlW, (short)ctlIOutline );
GetDItem( ctlW, ctlIEdit, &type, &item, &box ); /* Disable editText reporting and select text. */
SetDItem( ctlW, ctlIEdit, type | itemDisable, item, &box );
SelIText( ctlW, ctlIEdit, 0, 1000 );
GetDItem( ctlW, dlogIScroll, &type, &item, &box ); /* Disable scroll bar reporting. */
SetDItem( ctlW, dlogIScroll, type | itemDisable, item, &box );
SetCtlAction( item, ShowNewSize ); /* NOT an actionProc! Just a place to store an Update proc. */
SetCRefCon( item, 10 );
SetPort( oldPort );
/* // */
/* Get the new size. */
do { /* Loop lets the user get help. */
ModalDialog( DialogFilter, &itemHit );
switch( itemHit ) {
case ctlIHelp:
DoHelp();
break;
case ctlICancel:
NoRamDisk();
ExitToShell();
case ctlIBigDir:
GetDItem( ctlW, ctlIBigDir, &type, &item, &box );
SetCtlValue( item, 1-GetCtlValue(item) );
break;
}
} while( itemHit != ctlISet );
GetDItem( ctlW, ctlIEdit, &type, &item, &box );
GetIText( item, sizePstr );
StringToNum( sizePstr, &size );
GetDItem( ctlW, ctlIBigDir, &type, &item, &box );
dirSize = GetCtlValue(item) ? 3 : 1;
if( size < MinDisk/1024 ) /* Force the size to be reasonable. If the scroll */
size = MinDisk/1024; /* bar was used, it set the editText field to a */
if( size > maxDisk ) /* reasonable value already. */
size = maxDisk;
/* Save the new size and make a RAM disk that size. */
NoRamDisk();
ramStart = ramInfo.oldBufPtr - size * 1024; /* When we run again, make a new RAM */
/* disk with the new size. */
ramDesc = GetResource( 'RAMD', 256 );
*(long *)*ramDesc = heapSize = ramStart - (Ptr)GetZone();
ramDirSize = GetResource( 'RAMD', 257 );
*(long *)*ramDirSize = dirSize;
ChangedResource( ramDesc );
ChangedResource( ramDirSize );
if( ! ResError() )
UpdateResFile( HomeResFile(ramDesc) ); /* in either our file or a control file */
switch( ResError() ) {
case 0:
break;
case wPrErr:
case fLckdErr:
case vLckdErr:
Alert( alrtDiskProt, NULL );
break;
default:
error("\ptrouble saving ramDesc, resError=^2", (long)ResError());
}
InitRamDisk( heapSize, ramStart, dirSize );
ReStartUs(); /* Never returns. */
}
/* // */
/* Display the Help dialog. It contains text, a TextEdit field, a scroll
bar, a Continue button, and several radio buttons, one for each chapter.
The TextEdit field scrolls in response to the scroll bar, and its text
cannot be edited. */
static TEHandle helpTE; /* Used by ShowHelp() also. */
DoHelp()
{
DialogPtr help;
short type;
Handle item, version;
Rect box, dest;
static Rect copyRect = { 46, 10, 78, 273 };
extern char copyRight[];
pascal void DisplayHelp();
GrafPtr oldPort;
Handle helpText;
short itemHit, currentHelp, oldFont;
pascal void TOutline();
char str[MAXLINE];
help = GetNewDialog( dlogHelp, NULL, -1 ); /* Initially invisible. */
version = GetResource( 'GANr', 0 );
BlockMove( *version, str, (*version)[0] + 1 );
BlockMove( copyRight, &str[ str[0]+1 ], copyRight[0] + 1 );
str[ str[0]+1 ] = '\r';
str[0] += copyRight[0] + 1;
GetDItem( help, helpIName, &type, &item, &box );
SetIText( item, str );
GetDItem( help, helpIOutline, &type, &item, &box ); /* userItems */
SetDItem( help, helpIOutline, type, Outline, &box );
GetDItem( help, helpITOutline, &type, &item, &box );
SetDItem( help, helpITOutline, type, TOutline, &box );
GetDItem( help, helpIIcon, &type, &item, &box ); /* our icon */
SetDItem( help, helpIIcon, type, GetResource('ICN#', 128), &box );
GetDItem( help, helpIText, &type, &item, &box );
SetDItem( help, helpIText, type, DisplayHelp, &box );
GetPort( &oldPort ); /* Make a TERec in the Dialog box. */
SetPort( help );
dest = box;
InsetRect( &dest, 4, 0 );
oldFont = thePort->txFont;
thePort->txFont = 1; /* Application font. */
helpTE = TENew( &dest, &box );
thePort->txFont = oldFont;
SetPort( oldPort );
ShowWindow( help ); /* Show it now, 'cause there'll be a wait. */
BeginUpdate( help ); /* Normally done via Update event. */
DrawDialog( help );
EndUpdate( help );
/* // */
GetDItem( help, helpStarting, &type, &item, &box ); /* choose default text */
SetCtlValue( item, 1 );
SetHelp( helpStarting, help );
currentHelp = helpStarting;
while( TRUE ) {
ModalDialog( DialogFilter, &itemHit );
if( itemHit < helpStarting || itemHit > helpBCS )
break;
if( itemHit != currentHelp ) {
GetDItem( help, currentHelp, &type, &item, &box );
SetCtlValue( item, 0 );
GetDItem( help, itemHit, &type, &item, &box );
SetCtlValue( item, 1 );
SetHelp( itemHit, help );
currentHelp = itemHit;
}
}
DisposDialog( help );
}
SetHelp( helpItem, help )
short helpItem;
DialogPtr help;
{
short type;
Handle item, helpText;
Rect box, view, dest;
void ShowHelp();
GrafPtr oldPort;
GetPort( &oldPort ); /* We're going to put text in it. */
SetPort( help );
SetCursor( *GetCursor(watchCursor) );
view = dest = (*helpTE)->viewRect; /* display top line of text */
InsetRect( &dest, 4, 0 );
(*helpTE)->destRect = dest;
EraseRect( &view );
InvalRect( &view );
helpText = GetResource( 'HELP', 256+helpItem-helpStarting ); /* Get the help text. */
(*helpTE)->hText = helpText;
(*helpTE)->teLength = GetHandleSize( helpText );
TECalText( helpTE ); /* wait */
TESetSelect( 0, 0, helpTE ); /* at first line */
GetDItem( help, dlogIScroll, &type, &item, &box ); /* Set up the control. */
SetCtlMin( item, 1 );
SetCtlMax( item, (*helpTE)->nLines - 12 );
SetCtlValue( item, 1 );
SetCtlAction( item, ShowHelp ); /* NOT an actionProc! Update proc. */
SetCRefCon( item, 12 );
InitCursor();
SetPort( oldPort );
}
/* // */
/* Called by ModalDialog or Help to handle a scroll bar, which must have
the same item number in each dialog. It also detects Return and Enter so
they still exit the dialog. */
pascal Boolean DialogFilter( theDialog, theEventp, itemHitp )
DialogPtr theDialog; /* --> */
EventRecord *theEventp; /* <-> */
short *itemHitp; /* <-> */
{
GrafPtr oldPort;
Point thePoint;
short whichPart;
ControlHandle theControl;
short type;
Handle item;
Rect box;
short oldValue;
pascal void TrackScroll();
ProcPtr updateProc;
if( theEventp->what == keyDown /* So Return will exit the Dialog. */
&& ( (theEventp->message & charCodeMask) == '\r'
|| (theEventp->message & charCodeMask) == '\3' ) )
{
*itemHitp = 1;
return( TRUE );
}
if( theEventp->what == mouseDown ) {
GetPort( &oldPort );
SetPort( theDialog );
thePoint = theEventp->where;
GlobalToLocal( &thePoint );
whichPart = FindControl( thePoint, theDialog, &theControl);
GetDItem( theDialog, dlogIScroll, &type, &item, &box );
if( (Handle)theControl == item ) {
if( whichPart == inThumb ) {
oldValue = GetCtlValue( theControl );
TrackControl( theControl, thePoint, NULL );
updateProc = GetCtlAction( theControl );
(*updateProc)( theDialog, GetCtlValue(theControl), oldValue );
}
else TrackControl( theControl, thePoint, TrackScroll );
theEventp->what = nullEvent; /* We used this event. */
}
SetPort( oldPort );
}
return( FALSE ); /* Don't want ModalDialog to exit. */
}
/* // */
/* Track either scroll bar, performing repetitive actions. This is called
as a Pascal procedure; its parameters are on the stack. */
pascal void TrackScroll( theControl, partCode )
ControlHandle theControl; /* --> */
short partCode; /* --> */
{
char up;
short value;
short amount;
ProcPtr updateProc;
up = (partCode == inUpButton) || (partCode == inPageUp);
value = GetCtlValue( theControl );
if( partCode
&& (up ? (value > GetCtlMin( theControl ))
: (value < GetCtlMax( theControl ))) )
{
amount = up ? -1 : 1;
if( (partCode == inPageUp) || (partCode == inPageDown) )
amount *= (int)GetCRefCon( theControl );
SetCtlValue( theControl, value + amount );
updateProc = GetCtlAction( theControl );
(*updateProc)( (*theControl)->contrlOwner, GetCtlValue(theControl), value );
}
}
/* // */
/* The Update procs: */
/* Show the new size in the editText field. Current GrafPort is theDialog. */
void ShowNewSize( theDialog, newSize, oldSize )
DialogPtr theDialog; /* --> */
short newSize, oldSize; /* --> */
{
char sizePstr[32];
short type;
Handle item;
Rect box;
NumToString( newSize, sizePstr );
GetDItem( theDialog, ctlIEdit, &type, &item, &box );
SetIText( item, sizePstr );
SelIText( theDialog, ctlIEdit, 0, 1000 );
}
/* Show the Help text when it is scrolled. Assumes the TextEdit record. */
void ShowHelp( theDialog, newValue, oldValue )
DialogPtr theDialog; /* --> */
short newValue, oldValue; /* --> */
{
short linesMoved = newValue - oldValue;
TEScroll( 0, -(*helpTE)->lineHeight * linesMoved, helpTE );
BeginUpdate( theDialog ); /* Normally done via Update event. */
TEUpdate( &(*helpTE)->viewRect, helpTE );
EndUpdate( theDialog );
}
/* // */
/* Outline a button in a dialog. Called by DrawDialog(). */
pascal void Outline( theDialog, theItem )
WindowPtr theDialog; /* --> */
short theItem; /* --> */
{
short type;
Handle item;
Rect box;
PenState penState;
GetDItem( theDialog, theItem, &type, &item, &box );
GetPenState( &penState );
PenSize( 3, 3 );
InsetRect( &box, -4, -4 );
FrameRoundRect( &box, 16, 16 );
SetPenState( &penState );
}
/* // */
/* Outline a TextEdit field in a dialog. Called by DrawDialog(). */
pascal void TOutline( theDialog, theItem )
WindowPtr theDialog; /* --> */
short theItem; /* --> */
{
short type;
Handle item;
Rect box;
PenState penState;
GetDItem( theDialog, theItem, &type, &item, &box );
GetPenState( &penState );
PenNormal();
FrameRect( &box );
SetPenState( &penState );
}
/* // */
/* Display the Help text when DrawDialog() needs to. */
pascal void DisplayHelp( theDialog, theItem )
WindowPtr theDialog; /* --> */
short theItem; /* --> */
{
TEUpdate( &(*helpTE)->viewRect, helpTE );
TextFont( 0 ); /* sigh */
}
/* // */
/* Hide or show a dialog item, the way the new ROMs do (except for editText
items). */
myHideDItem( dlog, dItem )
DialogPtr dlog;
short dItem;
{
short type;
Handle item;
Rect box;
GrafPtr oldPort;
if( !dlog )
return;
GetDItem( dlog, dItem, &type, &item, &box );
if( box.left < 8192 ) {
GetPort( &oldPort );
SetPort( dlog );
EraseRect( &box );
InvalRect( &box );
SetPort( oldPort );
box.left += 16384;
box.right += 16384;
SetDItem( dlog, dItem, type, item, &box );
}
}
myShowDItem( dlog, dItem )
DialogPtr dlog;
short dItem;
{
short type;
Handle item;
Rect box;
GrafPtr oldPort;
if( !dlog )
return;
GetDItem( dlog, dItem, &type, &item, &box );
if( box.left >= 8192 ) {
box.left -= 16384;
box.right -= 16384;
GetPort( &oldPort );
SetPort( dlog );
InvalRect( &box );
SetPort( oldPort );
SetDItem( dlog, dItem, type, item, &box );
}
}
GrayBtn( dlog, dItem )
DialogPtr dlog;
short dItem;
{
short type;
Handle item;
Rect box;
GetDItem( dlog, dItem, &type, &item, &box );
HiliteControl( item, 255 );
SetDItem( dlog, dItem, type | itemDisable, item, &box );
}